using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using System.IO;
using LibNDSFormats.NSBMD;
using Tao.OpenGl;
using LibNDSFormats.NSBTX;
using Tao.FreeGlut;

namespace MKDS_Course_Editor
{
    public partial class HBDF_MDLF : Form
    {
        string file_ = "";
        //Nsbmd nsbm;
        //NsbmdGlRenderer t;
        MDLF.MDLF m = new MDLF.MDLF();
        public HBDF_MDLF(string file)
        {
            file_ = file;

            InitializeComponent();
            simpleOpenGlControl1.InitializeContexts();
            simpleOpenGlControl1.MouseWheel += new MouseEventHandler(simpleOpenGlControl1_MouseWheel);
        }

        void simpleOpenGlControl1_MouseWheel(object sender, MouseEventArgs e)
        {
            dist += (float)e.Delta / 1000;
            simpleOpenGlControl1.Invalidate();
            RenderFunc1();
        }

        private void nsbmd_Load(object sender, EventArgs e)
        {
            m = MDLF.MDLF.Read(file_);
            RenderFunc1();
        }
        public static float X = 0.0f;
        public static float Y = 0.0f;
        public static float ang = 0.0f;
        public static float dist = 0.0f;//2.5
        public static float elev = 0.0f;
        private void RenderFunc1()
        {
            Gl.glViewport(0, 0, this.Width, this.Height);
            var vp = new[] { 0f, 0f, 0f, 0f };
            Gl.glGetFloatv(Gl.GL_VIEWPORT, vp);
            float aspect = (vp[2] - vp[0]) / (vp[3] - vp[1]);
            Gl.glMatrixMode(Gl.GL_PROJECTION);
            Gl.glLoadIdentity();
            Glu.gluPerspective(90.0f, aspect, 0.02f, 50f);//0.02f, 32.0f);
            float gcd = GCD(Width, Height);

            Gl.glFrustum(-((float)Width / gcd), ((float)Width / gcd), -((float)Height / gcd), ((float)Height / gcd), 0, 0);  // apply the projection matrix
            //Gl.glEnable(Gl.GL_DITHER);
            //Gl.glEnable(Gl.GL_LINE_SMOOTH);
            Gl.glEnable(Gl.GL_POLYGON_SMOOTH);
            Gl.glEnable(Gl.GL_DEPTH_TEST);
            Gl.glEnable(Gl.GL_TEXTURE_2D);

            Gl.glEnable(Gl.GL_ALPHA_TEST);

            Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA);
            Gl.glEnable(Gl.GL_BLEND);
            Gl.glAlphaFunc(Gl.GL_GREATER, 0f);
            Gl.glTranslatef(X, Y, -dist);
            Gl.glRotatef(elev, 1, 0, 0);
            Gl.glRotatef(ang, 0, 1, 0);
            Gl.glMatrixMode(Gl.GL_MODELVIEW);
            Gl.glLoadIdentity();
            if (true)
            {
                Gl.glBindTexture(Gl.GL_TEXTURE_2D, 0);
                Gl.glBegin(Gl.GL_LINES);
                Gl.glColor3f(1.0f, 1.0f, 1.0f);
                Gl.glVertex3f(0.0f, 0.0f, 0.0f);
                Gl.glVertex3f(1.0f, 0.0f, 0.0f);
                Gl.glVertex3f(0.0f, 0.0f, 0.0f);
                Gl.glVertex3f(0.0f, 1.0f, 0.0f);
                Gl.glVertex3f(0.0f, 0.0f, 0.0f);
                Gl.glVertex3f(0.0f, 0.0f, 1.0f);
                Gl.glEnd();
                Gl.glRasterPos3f(1.0f, 0.0f, 0.0f);

                //Glut.glutBitmapCharacter(Glut.GLUT_BITMAP_HELVETICA_18, 'X');
                Gl.glRasterPos3f(0.0f, 1.0f, 0.0f);
                // Glut.glutBitmapCharacter(Glut.GLUT_BITMAP_HELVETICA_18, 'Y');
                Gl.glRasterPos3f(0.0f, 0.0f, 1.0f);

                //Glut.glutBitmapCharacter(Glut.GLUT_BITMAP_HELVETICA_18, 'Z');
            }


            Gl.glClearColor(51f / 255f, 51f / 255f, 51f / 255f, 1f);
            Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
            Gl.glDisable(Gl.GL_CULL_FACE);
            Glu.GLUquadric q = Glu.gluNewQuadric();
            Glu.gluSphere(q, 0.0201f, 50, 50);

            try
            {

                //HBDF.MDLF t = new HBDF.MDLF();
                //t.load(File.ReadAllBytes(file_));
                m.Render();
            }
            catch (Exception ex)
            {
            }
        }
        static int GCD(int a, int b)
        {
            return b == 0 ? a : GCD(b, a % b);
        }
        private void simpleOpenGlControl1_KeyUp(object sender, KeyEventArgs e)
        {


        }


        private void simpleOpenGlControl1_Scroll(object sender, ScrollEventArgs e)
        {

        }

        private void simpleOpenGlControl1_Click(object sender, EventArgs e)
        {

        }

        private void simpleOpenGlControl1_MouseDown(object sender, MouseEventArgs e)
        {

        }


        private void simpleOpenGlControl1_KeyDown(object sender, KeyEventArgs e)
        {


        }

        private void simpleOpenGlControl1_KeyPress(object sender, KeyPressEventArgs e)
        {

        }

        private void timer1_Tick(object sender, EventArgs e)
        {

        }

        private void nsbmd_KeyDown(object sender, KeyEventArgs e)
        {

        }
        public void MatchTextures()
        {
            /*for (var i = 0; i < models.Length; i++)
            {
                for (var j = 0; j < models[i].Materials.Count; j++)
                {
                    bool gottex = false;
                    bool gotpal = false;
                    foreach (var mat1 in materials)
                    {
                        if (j >= models[i].Materials.Count)
                            continue;
                        var mat2 = models[i].Materials[j];


                        // match texture
                        if (!gottex && mat1.texname.Equals(mat2.texname))
                        {
                            Console.WriteLine("tex '{0}' matched.", mat2.texname);
                            mat1.CopyTo(mat2);

                            gottex = true;
                        }
                        // match palette
                        if (mat2.format != 7 // NB. direct texture has no palette
                            && !gotpal
                            && (mat1.palname).Equals(mat2.palname))
                        {
                            Console.WriteLine("pal '{0}' matched.", mat1.palname);
                            mat2.palname = mat1.palname;
                            mat2.palsize = mat1.palsize;
                            mat2.paldata = mat1.paldata;
                            //mat1->palsize = 0;
                            gotpal = true;
                        }
                    }
                }
            }*/

            /*for (var i = 0; i < nsbm.models.Length; i++)
            {
                for (var j = 0; j < nsbm.models[i].Materials.Count; j++)
                {
                    bool gottex = false;
                    bool gotpal = false;
                    foreach (var mat1 in nsbm.materials)
                    {
                        if (j >= nsbm.models[i].Materials.Count)
                            continue;
                        var mat2 = nsbm.models[i].Materials[j];

                        // match texture
                        if (!gottex && mat1.texname.Equals(mat2.texname))
                        {
                            Console.WriteLine("tex '{0}' matched.", mat2.texname);
                            mat1.CopyTo(mat2);

                            gottex = true;
                        }
                        for (int q = 0; q < nsbm.materials.ToList().Count; q++)
                        {

                            if (mat2.format != 7 // NB. direct texture has no palette
                                && !gotpal
                                && nsbm.materials.ToList()[q].palname.Contains(mat2.texname)
                                && (mat1.palname).Equals(mat2.palname))
                            {
                                Console.WriteLine("pal '{0}' matched.", nsbm.materials.ToArray()[q].palname);
                                mat2.palname = nsbm.materials.ToArray()[q].palname;
                                mat2.palsize = nsbm.materials.ToArray()[q].palsize;
                                mat2.paldata = nsbm.materials.ToArray()[q].paldata;
                                //mat1->palsize = 0;
                                gotpal = true;
                            }
                        }
                        nsbm.models[i].Materials[j] = mat2;
                        /// match palette
                        if (mat2.format != 7 // NB. direct texture has no palette
                            && !gotpal
                            && (mat1.palname).Equals(mat2.palname))
                        {
                            Console.WriteLine("pal '{0}' matched.", mat1.palname);
                            mat2.palname = mat1.palname;
                            mat2.palsize = mat1.palsize;
                            mat2.paldata = mat1.paldata;
                            //mat1->palsize = 0;
                            gotpal = true;
                        }
                        // models[i].Materials[j] = mat2;
                    }
                }
            }*/
        }
        public bool wire = false;
        public bool fix = false;
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            switch (keyData)
            {
                case Keys.Right:
                    ang += 1;
                    simpleOpenGlControl1.Invalidate();
                    RenderFunc1();
                    return true;
                case Keys.Left:
                    ang -= 1;
                    simpleOpenGlControl1.Invalidate();
                    RenderFunc1(); ;
                    return true;
                case Keys.Up:
                    elev += 1;
                    simpleOpenGlControl1.Invalidate();
                    RenderFunc1(); ;
                    return true;
                case Keys.Down:
                    elev -= 1;
                    simpleOpenGlControl1.Invalidate();
                    RenderFunc1(); ;
                    return true;
                case Keys.Z:
                    X -= 0.1f;
                    simpleOpenGlControl1.Invalidate();
                    RenderFunc1(); ;
                    return true;
                case Keys.X:
                    X += 0.1f;
                    simpleOpenGlControl1.Invalidate();
                    RenderFunc1(); ;
                    return true;
                case Keys.A:
                    Y -= 0.1f;
                    simpleOpenGlControl1.Invalidate();
                    RenderFunc1(); ;
                    return true;
                case Keys.S:
                    Y += 0.1f;
                    simpleOpenGlControl1.Invalidate();
                    RenderFunc1(); ;
                    return true;
                case Keys.W:
                    if (wire == false)
                    {
                        Gl.glPolygonMode(Gl.GL_FRONT_AND_BACK, Gl.GL_LINE);
                        simpleOpenGlControl1.Invalidate();
                        RenderFunc1(); ;
                        wire = true;
                    }
                    else
                    {
                        Gl.glPolygonMode(Gl.GL_FRONT_AND_BACK, Gl.GL_FILL);
                        simpleOpenGlControl1.Invalidate();
                        RenderFunc1(); ;
                        wire = false;
                    }
                    return true;
                case Keys.Escape:
                    X = 0.0f;
                    Y = 0.0f;
                    ang = 0.0f;
                    dist = 0.0f;
                    elev = 0.0f;
                    simpleOpenGlControl1.Invalidate();
                    RenderFunc1(); ;
                    return true;
                case Keys.F:
                    if (fix == false)
                    {
                        
                        fix = true;
                    }
                    else
                    {
                        
                        fix = false;
                    }
                    return true;
                default:
                    return base.ProcessCmdKey(ref msg, keyData);
            }
        }

        private void simpleOpenGlControl1_Resize(object sender, EventArgs e)
        {
            simpleOpenGlControl1.Invalidate();
            RenderFunc1();
        }

        private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
        {

        }


    }
}
